﻿using System;
using System.Collections.Generic;
using System.IO;
using EmployeeApp.DAL.Dal;
using EmployeeApp.DAL.Models.Employee;
using EmployeeApp.DAL.Entities;
using EmployeeApp.Service.Dto.Branch;
using EmployeeApp.Service.Dto.Position;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Tool.hbm2ddl;
using EmployeeApp.Service.Dto.Employee;
using FluentNHibernate.Automapping;
using Configuration = NHibernate.Cfg.Configuration;
using GetAllRequestDto = EmployeeApp.Service.Dto.Employee.GetAllRequestDto;

namespace EmployeeApp.Service
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "EmployeeService" in code, svc and config file together.
    // NOTE: In order to launch WCF Test Client for testing this service, please select EmployeeService.svc or EmployeeService.svc.cs at the Solution Explorer and start debugging.
    public class EmployeeService : IEmployeeService
    {
        public ISession Session;
        readonly ISessionFactory _sessionFactory;
        public EmployeeService()
        {
            var appReader = new System.Configuration.AppSettingsReader();
            var connectionString = Convert.ToString(appReader.GetValue("connectionString", typeof(string)));
            var mappingScriptPath = AppDomain.CurrentDomain.BaseDirectory + "/db_mappings";
            if (!Directory.Exists(mappingScriptPath))
                Directory.CreateDirectory(mappingScriptPath);

            _sessionFactory = Fluently.Configure()
                .Database(
                    MsSqlConfiguration.MsSql2008
                    .ConnectionString(@connectionString))
                    .Mappings(x => x.AutoMappings.Add(AutoMap.AssemblyOf<Employee>().Where(t => t.Namespace.EndsWith("Entities"))).ExportTo(@mappingScriptPath))
                //.ExposeConfiguration(BuildSchema) // ********** ใช้ครั้งแรกเท่านั้น (กรณียังไม่มี Table)
                    .BuildSessionFactory();
            Session = _sessionFactory.OpenSession();
        }
        private static void BuildSchema(Configuration config)
        {
            new SchemaExport(config).Create(false, true);
        }

        public Dto.Employee.ResponseDto<List<EmployeeDto>> GetAll(GetAllRequestDto arg)
        {
            var result = new Dto.Employee.ResponseDto<List<EmployeeDto>>();
            try
            {
                var dal = new EmployeeDAL(Session);

                SearchCriteria search = null;
                if (arg != null)
                {
                    search = new SearchCriteria
                                 {
                                     EmpId = arg.EmpId,
                                     Name = arg.Name,
                                     Sort = arg.Sort,
                                     SortType = arg.SortType,
                                     Status = arg.Status,
                                 };
                }

                var list = dal.GetAll(search);
                result.Data = new List<EmployeeDto>();
                if (list.Count > 0)
                {
                    foreach (var item in list)
                    {
                        var dto = TransformEmployee2Dto(item);
                        result.Data.Add(dto);
                    }
                }
                result.Status = true;
            }
            catch (Exception ex)
            {
                result.Status = false;
                result.ErrorMessage = ex.Message;
            }
            return result;
        }



        public Dto.Employee.ResponseDto<EmployeeDto> Add(EmployeeDto arg)
        {
            var result = new Dto.Employee.ResponseDto<EmployeeDto>();
            using (Session.BeginTransaction())
            {
                try
                {
                    var dal = new EmployeeDAL(Session);
                    var obj = TransformDto2Employee(arg);
                    dal.Add(obj);
                    Session.Transaction.Commit();
                    result.Status = true;
                }
                catch (Exception ex)
                {
                    Session.Transaction.Rollback();
                    result.Status = false;
                    result.ErrorMessage = ex.Message;
                }
            }
            return result;
        }

        public Dto.Employee.ResponseDto<EmployeeDto> Update(EmployeeDto arg)
        {
            var result = new Dto.Employee.ResponseDto<EmployeeDto>();

            using (Session.BeginTransaction())
            {
                try
                {
                    var dal = new EmployeeDAL(Session);
                    var obj = TransformDto2Employee(arg);
                    dal.Update(obj);
                    Session.Transaction.Commit();
                    result.Status = true;

                }
                catch (Exception ex)
                {
                    Session.Transaction.Rollback();
                    result.Status = false;
                    result.ErrorMessage = ex.Message;
                }
            }
            return result;
        }

        public Dto.Employee.ResponseDto<EmployeeDto> Delete(List<string> arg)
        {
            var result = new Dto.Employee.ResponseDto<EmployeeDto>();
            using (Session.BeginTransaction())
            {
                try
                {
                    var obj = new EmployeeDAL(Session);
                    obj.Delete(arg);
                    Session.Transaction.Commit();
                    result.Status = true;
                }
                catch (Exception ex)
                {
                    Session.Transaction.Rollback();
                    result.Status = false;
                    result.ErrorMessage = ex.Message;
                }
            }
            return result;
        }

        private EmployeeDto TransformEmployee2Dto(Employee arg)
        {
            var dto = new EmployeeDto();
            dto.Id = arg.Id;
            dto.Hired = arg.Hired;
            dto.Title = arg.Title;
            dto.Name = arg.Name;
            dto.EmpId = arg.EmpId;
            dto.Status = arg.Status;
            dto.Surname = arg.Surname;
            dto.Address = arg.Address;
            dto.JobTitle = new PositionDto();
            if (null != arg.JobTitle)
            {
                dto.JobTitle.Code = arg.JobTitle.Code;
                dto.JobTitle.Id = arg.JobTitle.Id;
                dto.JobTitle.Name = arg.JobTitle.Name;
            }
            dto.BirthDate = arg.BirthDate;
            dto.Branch = new BranchDto();
            if (null != arg.Branch)
            {
                dto.Branch.Code = arg.Branch.Code;
                dto.Branch.Fax = arg.Branch.Fax;
                dto.Branch.Id = arg.Branch.Id;
                dto.Branch.Name = arg.Branch.Name;
                dto.Branch.Phone = arg.Branch.Phone;
            }
            dto.MarriedStatus = arg.MarriedStatus;
            return dto;
        }

        private Employee TransformDto2Employee(EmployeeDto arg)
        {
            var obj = new Employee();
            obj.Id = arg.Id;
            obj.Hired = arg.Hired;
            obj.Title = arg.Title;
            obj.Name = arg.Name;
            obj.EmpId = arg.EmpId;
            obj.Status = arg.Status;
            obj.Surname = arg.Surname;
            obj.Address = arg.Address;
            obj.JobTitle = new Position();
            if (null != arg.JobTitle)
            {
                obj.JobTitle.Code = arg.JobTitle.Code;
                obj.JobTitle.Id = arg.JobTitle.Id;
                obj.JobTitle.Name = arg.JobTitle.Name;
            }
            obj.BirthDate = arg.BirthDate;
            obj.Branch = new Branch();
            if (null != arg.Branch)
            {
                obj.Branch.Code = arg.Branch.Code;
                obj.Branch.Fax = arg.Branch.Fax;
                obj.Branch.Id = arg.Branch.Id;
                obj.Branch.Name = arg.Branch.Name;
                obj.Branch.Phone = arg.Branch.Phone;
            }
            obj.MarriedStatus = arg.MarriedStatus;
            return obj;
        }
    }
}
